package com.yricky.memoria.data

import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import com.google.gson.annotations.Expose
import com.yricky.memoria.utils.UID
import com.yricky.memoria.utils.globalContext
import java.io.File
import java.util.*
import kotlin.collections.ArrayList

/**
 * @author Yricky
 * @date 2021/11/21
 */
class SubjectModel(
    val model:WorkSpaceModel,
    private val dir: File,
    var metaData: WorkSpaceModel.SubjectMetaData
    ) {
    init {
        if(!dir.exists()){
            dir.mkdirs()
        }
    }
    val assetsDir get() = File(dir,"assets").also {
        if(!it.exists())
            it.mkdirs()
    }

    val uid get() = dir.name
    val name get() = metaData.name
    private val sectionModels:WeakHashMap<String/* uid */,Section> = WeakHashMap()

    fun addSection(name:String):SectionMetaData?{
        if(name.length > 40){
            return null
        }

        val uid:String = UID.section()
        val values = ContentValues()
        values.put(SUID, uid)
        values.put(SNAME,name)

        // Section MetaData写入数据库
        dbHelper.db.insert(
            SectionMetaTable.NAME,
            null,
            values
        )

        return SectionMetaData(
            uid = uid,
            name = name
        )
    }

    fun delSection(metaData: SectionMetaData):Boolean{
        if(File(dir,metaData.uid).deleteRecursively()){
            // 删除成功
        } else {
            // 删除失败
            return false
        }

        sectionModels.remove(metaData.uid)
        dbHelper.db.delete(
            SectionMetaTable.NAME,
            "$SUID = ?",
            arrayOf(metaData.uid)
        )
        return true
    }

    fun modSection(metaDataOld: SectionMetaData,metaDataNew: SectionMetaData):Boolean{
        if(metaDataOld.uid != metaDataNew.uid){
            return false
        }

        dbHelper.db.execSQL(
            "insert or replace into ${SectionMetaTable.NAME}($SUID,$SNAME) values(?,?)",
            arrayOf(metaDataOld.uid,metaDataNew.name)
        )

        return true
    }

    fun getSections(name: String = ""):List<SectionMetaData>{
        return dbHelper.db.query(
            SectionMetaTable.NAME,
            arrayOf(SUID, SNAME),
            "$SNAME like ?",
            arrayOf("$name%"),
            null,
            null,
            SNAME,
            null
        ).use{
            val list = ArrayList<SectionMetaData>()

            val uidIndex = it.getColumnIndex(SUID)
            val nameIndex = it.getColumnIndex(SNAME)

            if(
                uidIndex >= 0
                && nameIndex >= 0
                && it.count > 0
            ){
                it.moveToFirst()
                (0 until it.count).forEach { _ ->
                    list.add(
                            SectionMetaData(
                                uid = it.getString(uidIndex),
                                name = it.getString(nameIndex)
                            )
                    )
                    it.moveToNext()
                }
            }

            list
        }
    }

    /**
     * 给一个历史的SubjectMetaData，获取现在该MetaData的状态。
     * 若返回的MetaDataUID为空，则该subject已经被删除。
     */
    fun querySectionStat(metaData: SectionMetaData): SectionMetaData {
        return dbHelper.db.query(
            SectionMetaTable.NAME,
            arrayOf(SUID, SNAME),
            "$SUID like ?",
            arrayOf(metaData.uid),
            null,
            null,
            SNAME,
            null
        ).use{
            val uidIndex = it.getColumnIndex(SUID)
            val nameIndex = it.getColumnIndex(SNAME)

            if(
                uidIndex >= 0 &&
                nameIndex >= 0 &&
                it.count == 1
            ){
                it.moveToFirst()
                SectionMetaData(
                    uid = it.getString(uidIndex),
                    name = it.getString(nameIndex),
                )
            }else{
                SectionMetaData("", "")
            }
        }
    }

    fun openSection(metaData:SectionMetaData):Section?{
        return sectionModels[metaData.uid] ?: querySectionStat(metaData).let { mdNew ->
            if(mdNew.uid.isNotBlank()){
                Section(
                    this,
                    File(dir,mdNew.uid),
                    mdNew
                ).also {
                    // 缓存
                    sectionModels[it.uid] = it
                }
            }else null
        }
    }

    val tagManager:TagManager by lazy{
        TagManager(globalContext,dir, SUID)
    }


    companion object{
        const val DB_VERSION = 1
        private const val SUID = "secUid"
        const val SNAME = "name"
        private object SectionMetaTable{
            const val NAME = "secMetadata"
            fun initIn(db:SQLiteDatabase){
                db.execSQL("create table $NAME(${SUID} text primary key not null,$SNAME text not null)")
            }
        }
    }

    private val dbHelper = object : SQLiteOpenHelper(
        globalContext,
        File(dir,"metadata.db").path,
        null,
        WorkSpaceModel.DB_VERSION
    ){
        val db by lazy { writableDatabase }

        override fun onCreate(db: SQLiteDatabase?) {
            db?.transaction {
                SectionMetaTable.initIn(this)
            }
        }

        override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {

        }

    }

    class SectionMetaData(
        @Expose val uid:String,
        @Expose val name:String
    )

}